from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
from django.db.models import Q
from django.db import transaction
from .models import *
from .serializers import *
from .docs import *
from drf_yasg.utils import swagger_auto_schema
from rest_framework.permissions import IsAuthenticated, AllowAny
from utils.qiniu_tools import ImageHandler
from utils.nsfwChecker import NSFWChecker
from django.core.cache import cache


class CategoryViewSet(viewsets.ReadOnlyModelViewSet):
    permission_classes = [AllowAny]
    queryset = Category.objects.all()
    def get_cache_key(self, action_name):
        """生成缓存键"""
        return f'category_{action_name}_v1'
    
    
    @swagger_auto_schema(**CategoryViewsetDocs['list'])
    def list(self, request, *args, **kwargs):
        print("[DEBUG] CategoryViewSet.list 被调用")
        print(f"[DEBUG] request.user: {request.user}, is_authenticated: {request.user.is_authenticated}")
        """获取分类"""
        cache_key = self.get_cache_key('all')
        data = cache.get(cache_key)
        if data:
            response= Response(data)
            response['X-Data-Source'] = 'cache'
            print(f"[DEBUG] 缓存命中 - key: {cache_key}")  # 服务端控制台输出
            return response
        elif not data:
            roots = Category.objects.filter(is_root=True).order_by('sort_order')
            data = []
            for root in roots:
                children = Category.objects.filter(parent=root).order_by('sort_order')
                data.append({
                    'id': root.id,
                    'name': root.name,
                    'display_name': root.display_name,
                    'children': [
                        {'id': child.id, 'name': child.name,'display_name': child.display_name}
                        for child in children
                    ]
                })
            cache.set(cache_key, data, timeout=60*60*24) #缓存24小时
        return Response(data)
    def get_serializer_class(self):
        if self.action == 'list':
            return CategoryTreeSerializer
        return CategorySerializer
    
    @swagger_auto_schema(**CategoryViewsetDocs['choices'])
    @action(detail=False, methods=['get'])
    def choices(self, request):
        """获取分类选择项（用于前端下拉框）"""
        cache_key = self.get_cache_key('all')
        data = cache.get(cache_key)
        if data:
            response= Response(data)
            response['X-Data-Source'] = 'cache'
            print(f"[DEBUG] 缓存命中 - key: {cache_key}")  # 服务端控制台输出
            return response
        elif not data:
            roots = Category.objects.filter(is_root=True).order_by('sort_order')
            data = []
            for root in roots:
                children = Category.objects.filter(parent=root).order_by('sort_order')
                data.append({
                    'id': root.id,
                    'name': root.name,
                    'display_name': root.display_name,
                    'children': [
                        {'id': child.id, 'name': child.name,'display_name': child.display_name}
                        for child in children
                    ]
                })
            cache.set(cache_key, data, timeout=60*60*24) #缓存24小时
        return Response(data)
    
    @swagger_auto_schema(**CategoryViewsetDocs['roots'])
    @action(detail=False, methods=['get'])
    def roots(self, request):
        """获取所有一级分类"""
        queryset = Category.objects.filter(is_root=True).order_by('sort_order')
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)
    
    @swagger_auto_schema(**CategoryViewsetDocs['children'])
    @action(detail=True, methods=['get'])
    def children(self, request, pk=None):
        """获取指定分类的子分类"""
        cache_key = self.get_cache_key(f'children_{pk}')
        data = cache.get(cache_key)
        if not data:
            parent = self.get_object()
            if not parent.is_root:
                return Response([])
            queryset = Category.objects.filter(parent=parent).order_by('sort_order')
            serializer = CategorySerializer(queryset, many=True)
            data = serializer.data
            cache.set(cache_key, data, timeout=60*60*24)
        return Response(serializer.data)
    
    @swagger_auto_schema(**CategoryViewsetDocs['products'])
    @action(detail=True, methods=['get'])
    def products(self, request, pk=None):
        """获取指定分类下的商品列表"""
        category = self.get_object()
        exclude_product_code = request.query_params.get('exclude')
        
        # 1. 使用 select_related 和 prefetch_related 优化查询
        base_query = Product.objects.select_related(
            'category', 
            'seller'
        ).prefetch_related(
            'images'
        ).only(
        'id', 'name', 'price', 'status', 'product_code',
        'category', 'created_at', 'seller',
        'seller__username', 'seller__avatar_key', 'seller__credit_score',  # 修改这里，使用正确的字段名
        'images__image_url', 'images__display_order'
    )
        
        # 2. 优化分类查询
        if category.is_root:
            sub_category_ids = Category.objects.filter(
                parent=category
            ).values_list('id', flat=True)
            products = base_query.filter(
                category_id__in=sub_category_ids, 
                status=1
            )
        else:
            products = base_query.filter(
                category=category, 
                status=1
            )
        
        # 排除指定的商品
        if exclude_product_code:
            products = products.exclude(product_code=exclude_product_code)
        
        # 3. 优化排序
        sort = request.query_params.get('sort', '-created_at')
        if sort in ['price', '-price', 'created_at', '-created_at']:
            products = products.order_by(sort)
        
        # 4. 添加缓存
        cache_key = f'category_products_{category.id}_{sort}_{exclude_product_code}'
        cached_data = cache.get(cache_key)
        
        if cached_data:
            return Response(cached_data)
        
        # 5. 分页处理
        page = self.paginate_queryset(products)
        serializer = ProductListSerializer(page, many=True)
        response_data = self.get_paginated_response(serializer.data)
        
        # 6. 设置缓存
        cache.set(cache_key, response_data.data, timeout=60*5)  # 缓存5分钟
        
        return response_data

class SellerViewSet(viewsets.ModelViewSet):
    
    queryset = Product.objects.all().order_by('-created_at')
    serializer_class = SellerProductSerializer
    permission_classes = [IsAuthenticated]
    lookup_field = 'product_code'
    def get_queryset(self):
        return super().get_queryset().filter(seller=self.request.user)

    def perform_create(self, serializer):
        if not self.request.user.is_authenticated:
            raise serializers.ValidationError("用户未登录")
        is_publish = self.request.data.get('action') == 'publish'
        status = 1 if is_publish else 0
        serializer.save(seller=self.request.user, status=status)
    
   
    @transaction.atomic
    def create(self, request, *args, **kwargs):
        """原子化创建商品（包含图片上传）"""
        try:
            # 1. 处理商品基础信息
            data = request.data.copy()
            data['seller'] = request.user.id
            
            # 2. 验证并创建商品
            serializer = self.get_serializer(data=data)
            serializer.is_valid(raise_exception=True)
            # 3. 先检查图片（如果有）
            if 'multipart/form-data' in request.content_type:
                images_data = request.FILES.getlist('images', [])
                if images_data:
                    try:
                        pass
                        # imageChecker = NSFWChecker()
                        # imageChecker.check_images(images_data)
                    except ValueError as e:
                        return Response(
                            {"error": "图片审核失败", "message": str(e)},
                            status=status.HTTP_400_BAD_REQUEST
                        )
                    except request.exceptions.RequestException as e:
                        return Response(
                            {"error": "图片审核服务不可用", "message": str(e)},
                            status=status.HTTP_503_SERVICE_UNAVAILABLE
                        )
            # 修改这里，使用perform_create来保存
            self.perform_create(serializer)
            product = serializer.instance
            
            # 3. 处理图片上传（复用现有逻辑）
            if 'multipart/form-data' in request.content_type:
                handler = ImageHandler()
                for image_file in images_data:
                    upload_result = handler.upload_product_image(image_file, product)
                    ProductImage.objects.create(
                        product=product,
                        image_url=upload_result['key'],
                        display_order=product.images.count(),
                        size=image_file.size
                    )
            return Response(serializer.data, status=status.HTTP_201_CREATED)
            
        except serializers.ValidationError as e:
            return Response(e.detail, status=status.HTTP_400_BAD_REQUEST)
        except Exception as e:
            return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)

    @swagger_auto_schema(**SellerViewsetDocs['destroy'])
    def destroy(self, request, *args, **kwargs):
        """删除商品（同时删除关联图片记录和七牛云文件）"""
        product = self.get_object()
        try:
            # 1. 删除七牛云上的图片文件
            handler = ImageHandler()
            for image in product.images.all():
                handler.delete_file(image.image_url)
            
            # 2. 删除数据库中的图片记录
            product.images.all().delete()
            # 3. 删除商品记录
            return super().destroy(request, *args, **kwargs)
            
        except Exception as e:
            return Response(
                {"error": f"删除失败: {str(e)}"},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )
        
    @swagger_auto_schema(**SellerViewsetDocs['update'])
    @transaction.atomic
    def update(self, request, *args, **kwargs):
        """更新商品信息（增量更新图片）"""
        try:
            product = self.get_object()
            handler = ImageHandler()
            if 'deleted_images' in request.data:
                deleted_ids = request.data.getlist('deleted_images')
                images_to_delete = product.images.filter(id__in=deleted_ids)
                image_urls = [img.image_url for img in images_to_delete]
                for img in images_to_delete:
                    handler.delete_file(img.image_url)
            
                # 再删除数据库记录
                deleted_count, _ = images_to_delete.delete()
            
            # 先处理图片审核（必须在事务开始阶段）
            if 'multipart/form-data' in request.content_type:
                images_data = request.FILES.getlist('images', [])
                if images_data:
                    imageChecker = NSFWChecker()
                    imageChecker.check_images(images_data)  # 审核失败会直接抛异常
            

            if 'multipart/form-data' in request.content_type:
                existing_images = set(img.image_url for img in product.images.all())
                for image_file in images_data:
                    upload_result = handler.upload_product_image(image_file, product)
                    if upload_result['key'] not in existing_images:
                        ProductImage.objects.create(
                            product=product,
                            image_url=upload_result['key'],
                            display_order=product.images.count(),
                            size=image_file.size
                        )

            serializer=self.get_serializer(product, data=request.data, partial=True)
            serializer.is_valid(raise_exception=True)
            self.perform_update(serializer)

            return Response(serializer.data)
        except serializers.ValidationError as e:
            return Response(e.detail, status=status.HTTP_400_BAD_REQUEST)
        except Exception as e:
            return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
    @swagger_auto_schema(**SellerViewsetDocs['retrieve'])
    def retrieve(self, request, *args, **kwargs):
        """获取商品详情"""
        return super().retrieve(request, *args, **kwargs)

    @swagger_auto_schema(**SellerViewsetDocs['list'])
    def list(self, request, *args, **kwargs):
        """获取商品列表"""
        return super().list(request, *args, **kwargs)


    @swagger_auto_schema(**SellerViewsetDocs['unpublish'])
    @action(detail=True, methods=['post'], url_path='unpublish')
    def unpublish(self, request, product_code=None):
        product = self.get_object()
        if product.seller != request.user:
            return Response({'error': '无权操作'}, status=status.HTTP_403_FORBIDDEN)
        product.status = 4
        product.save()
        return Response({'status': product.status})

    @swagger_auto_schema(**SellerViewsetDocs['republish'])
    @action(detail=True, methods=['post'], url_path='republish')
    def republish(self, request, product_code=None):
        product = self.get_object()
        product.status = 1
        product.created_at = timezone.now()
        product.save()
        return Response({'status': product.status})
    
    @swagger_auto_schema(**SellerViewsetDocs['price'])
    @action(detail=True, methods=['post'], url_path='change-price')
    def price(self,request, product_code=None):
        product = self.get_object()
        if product.seller != request.user:
            return Response({'error': '无权操作'}, status=status.HTTP_403_FORBIDDEN)
        try:
            new_price = float(request.data.get('new_price', 0))
            if new_price <= 0:
                return Response({'error': '价格必须大于0'}, status=status.HTTP_400_BAD_REQUEST)
            old_price = product.price
            product.price = new_price
            product.save()
            return Response({
                'message': '降价成功',
                'old_price': old_price,
                'new_price': new_price
            })
        
        except (TypeError, ValueError):
            return Response({'error': '价格格式无效'}, status=status.HTTP_400_BAD_REQUEST)
        except Exception as e:
            return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)
 
class BuyerViewSet(viewsets.ReadOnlyModelViewSet):
    """
    买家API
    """
    serializer_class = BuyerProductSerializer
    permission_classes = [AllowAny]
    lookup_field = 'product_code'  # 修改前为默认ID
    lookup_url_kwarg = 'product_code'
    
    # 重写retrieve使用主键ID
    def get_object(self):
        """重写get_object方法，限制可访问的商品状态"""
        queryset = self.filter_queryset(
            Product.objects.filter(status__in=[1, 2, 3])
        )
        try:
            obj = queryset.get(product_code=self.kwargs['product_code'])
            self.check_object_permissions(self.request, obj)
            return obj
        except Product.DoesNotExist:
            raise serializers.ValidationError("商品不存在或已下架")


    @swagger_auto_schema(**BuyerViewsetDocs['retrieve'])
    def retrieve(self, request, *args, **kwargs):
        """获取当个商品信息"""
        return super().retrieve(request, *args, **kwargs)

    @swagger_auto_schema(**BuyerViewsetDocs['search'])
    @action(detail=False, methods=['get'], url_path='search')
    def search(self, request):
        queryset = Product.objects.filter(status=1)
        keyword = request.query_params.get('q')
        category_id = request.query_params.get('category')

        if keyword:
            queryset = queryset.filter(
                Q(name__icontains=keyword) | 
                Q(description__icontains=keyword)
            )

        if category_id:
            queryset = queryset.filter(category_id=category_id)

        serializer = BuyerProductSerializer(queryset.order_by('-created_at'), many=True)
        return Response(serializer.data)

    @swagger_auto_schema(method='post',**BuyerViewsetDocs['favorites']['POST'])
    @swagger_auto_schema( method='delete',**BuyerViewsetDocs['favorites']['DELETE'])
    @action(detail=True, methods=['post', 'delete'], url_path='favorites')
    def favorites(self, request, product_code=None):
        """收藏/取消收藏商品"""
        product = self.get_object()
        user = request.user
        
        if not user.is_authenticated:
            return Response({"error": "请先登录"}, status=status.HTTP_401_UNAUTHORIZED)

        with transaction.atomic():
            if request.method == 'POST':
                # 添加收藏
                favorite, created = Favorite.objects.select_for_update().get_or_create(
                    user=user,
                    product=product,
                    defaults={'user': user, 'product': product}
                )
                if not created:
                    return Response(
                        {"error": "商品已在收藏列表中"}, 
                        status=status.HTTP_400_BAD_REQUEST
                    )
                return Response(
                    {"status": "favorited", "message": "收藏成功"},
                    status=status.HTTP_201_CREATED
                )
                
            elif request.method == 'DELETE':
                # 取消收藏
                try:
                    favorite = Favorite.objects.select_for_update().get(
                        user=user,
                        product=product
                    )
                    favorite.delete()
                    return Response(
                        {"status": "unfavorited", "message": "已取消收藏"},
                        status=status.HTTP_200_OK
                    )
                except Favorite.DoesNotExist:
                    return Response(
                        {"error": "商品未收藏"},
                        status=status.HTTP_404_NOT_FOUND
                    )
    @action(methods=['get'], detail=True,  url_path='check-favorites')
    def check_favorites_list(self, request, product_code=None):
        """检查是否收藏"""
        user = request.user
        try:
            product = Product.objects.get(
                product_code=product_code,
                status__in=[1, 2]  # 只检查有效商品
            )
        except Product.DoesNotExist:
            return Response(
                {"error": "商品不存在或已下架"},
                status=status.HTTP_404_NOT_FOUND
            )
        if not request.user.is_authenticated:
            return Response(
                {"error": "请先登录"},
                status=status.HTTP_401_UNAUTHORIZED
            )
        is_favorite = Favorite.objects.filter(
            user=request.user,
            product=product
        ).exists()
        return Response({"isFavorite": is_favorite})
    @swagger_auto_schema(**BuyerViewsetDocs['favorites_list'])
    @action(detail=False, methods=['get'], url_path='favorites')
    def favorites_list(self, request):
        """获取用户收藏的商品"""
        user = request.user
        if not user.is_authenticated:
            return Response({"error": "请先登录"}, status=status.HTTP_401_UNAUTHORIZED)
        
        favoriteed_products = Favorite.objects.filter(user=user).values_list('product', flat=True)
        
        # 获取这些商品的实际数据（只包含已上架商品）
        products = Product.objects.filter(
            id__in=favoriteed_products,
            status__in=[1, 2]
        ).order_by('-created_at')
        
        # 分页处理
        page = self.paginate_queryset(products)
        if page is not None:
            serializer = BuyerProductSerializer(page, many=True)
            return self.get_paginated_response(serializer.data)
        
        serializer = BuyerProductSerializer(products, many=True)
        return Response(serializer.data)